﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Carbon.Web.Forms
{
    internal class PathUtility
    {
        private const String invalidRootOfPath = "Invalid root '{0}' of path '{1}'.";

        public static String Join(string path1, string path2, char separator)
        {
            if (path1.Length > 0 && path1[path1.Length - 1] == separator)
            {
                path1 = path1.Substring(0, path1.Length - 1);
            }
            if (path2.Length > 0 && path2[0] != separator)
            {
                path2 = separator + path2;
            }

            return path1 + path2;
        }

        public static String RelativeJoin(string current, string relative, char separator)
        {
            if (relative.StartsWith("/"))
                return relative;

            List<string> aNames = new List<string>(current.Split(separator));
            String[] aCommands = relative.Split(separator);

            foreach (string command in aCommands)
            {
                if (command == string.Empty) continue;

                if (command == ".") { }
                else if (command == "..")
                {
                    if (aNames.Count > 2 || (aNames.Count == 1 && aNames[0] != string.Empty))
                        aNames.RemoveAt(aNames.Count - 1);
                }
                else
                    aNames.Add(command);
            }

            if (aNames.Count == 1 && aNames[0] == "")
                return "/";


            return string.Join(separator.ToString(), aNames.ToArray());
        }

        public static String LastElement(String path, char separator)
        {
            int last = path.LastIndexOf(separator);

            last = last + 1;
            if (last > path.Length)
                last = path.Length;

            return path.Substring(last);
        }

        public static String FromAbsoluteToRelative(String absolutePath, String root, char separator)
        {
            return FromAbsoluteToRelative(absolutePath, root, separator, true);
        }

        public static String FromAbsoluteToServerRelative(String absolutePath, char separator)
        {
            Uri pathUri = new Uri(absolutePath, UriKind.RelativeOrAbsolute);

            return separator + pathUri.GetComponents(UriComponents.Path, UriFormat.Unescaped);
        }

        public static String FromAbsoluteToRelative(String absolutePath, String root, char separator, bool caseInsensitive)
        {
            String relativePath;

            StringComparison compareWith = caseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;

            if (string.Compare(absolutePath, root, compareWith) == 0)
            {
                relativePath = string.Empty;
            }
            else if (absolutePath.StartsWith(root + separator, compareWith))
            {
                relativePath = absolutePath.Substring(root.Length + 1);
            }
            else
            {
                throw new ArgumentException(String.Format(invalidRootOfPath, root, absolutePath));
            }

            return relativePath;
        }

        public static String GetParentPath(string path, char separator)
        {
            if (string.IsNullOrEmpty(path)) throw new ArgumentOutOfRangeException("path");

            int lastIndexOfSeparator = path.LastIndexOf(separator);

            if (lastIndexOfSeparator >= 0)
                return path.Substring(0, lastIndexOfSeparator);
            else
                return null;
        }

        public static String GetSchemeAndServer(String uri)
        {
            Uri absoluteUri = new Uri(uri);
            return absoluteUri.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped);
        }
    }
}
